home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
tcp_ip
/
os2
/
pmnos11s
/
lpd.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-30
|
25KB
|
1,015 lines
/* Internet LPD Server
* written by David Johnson (dave@cs.olemiss.edu)
*
* This code is in the public domain.
*
* Revision History:
*
* Revision 1.5 91/09/28 dave
* Separate filenames in lpq -l with commas
* Log permission rejections to the queue error log file
*
* Revision 1.4 91/09/26 dave (from Hans-Juergen Knobloch)
* Reset secure flag on startup so the security features may be enabled
* and disabled without leaving net
* Changed definition of priority to char
* Changed definition of job size in send_queue() to a long
* Changed formatting of date in send_queue()
*
* Revision 1.3 91/09/19 dave
* Had to update is_job_specified() since additional letter sequence
*
* Revision 1.2 91/09/17 dave
* Job number reported to lpq included part which was not numeric
* Long hostname in send_queue() would overflow line buffer
* Date in send_queue() was not terminated properly
*
* Revision 1.1 91/09/14 dave
* Finished permission checking
*
* Revision 1.0 91/09/04 dave
* Initial Release
*
*/
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <sys/stat.h>
#ifdef __TURBOC__
#include <io.h>
#include <dir.h>
#endif
#include "global.h"
#include "mbuf.h"
#include "proc.h"
#include "iface.h"
#include "usock.h"
#include "socket.h"
#include "domain.h"
#include "dirutil.h"
#include "commands.h"
#include "files.h"
#include "lp.h"
#include "lpd.h"
/* in lpdunsp.c */
extern void start_all_unspoolers __ARGS((int s, void *unused, void *p));
extern void start_unspooler __ARGS((char *queue));
/* in lpdsubr.c */
extern void free_queue_status __ARGS((void));
extern int get_job_list __ARGS((char *directory, struct job_entry **job_list));
extern int get_new_sequence_no __ARGS((struct LPDtrans *LPD));
extern int init_queue_status __ARGS((void));
extern int is_unspooler_active __ARGS((char *queue, char **job));
extern int kill_unspooler __ARGS((char *queue));
extern void lpd_log __ARGS((struct LPDtrans *LPD, char *message, ...));
extern char *read_printcap __ARGS((struct LPDtrans *LPD, char *queue));
extern int read_status __ARGS((char *queue, unsigned int *flags, unsigned int *next_seq, char **message));
/* local functions - public */
char *extract_parms __ARGS((char *local_parms, int extra));
int is_job_specified __ARGS((char *cf_name));
int is_lpd_active __ARGS((void));
int lpd0 __ARGS((int argc, char *argv[], void *p));
int lpdstart __ARGS((int argc, char *argv[], void *p));
int trunc_strcat __ARGS((char *dest, char *source, int max_length));
/* local functions - private */
static int check_printer __ARGS((struct LPDtrans *LPD, char *printer_name));
static void cleanup __ARGS((char *spool_dir, char *filespec));
static int enter_translation __ARGS((struct LPDxlat *xlat_table, char *filename,
char *remotefile));
static int fixup_and_write_control_file __ARGS((struct LPDtrans *LPD, char *filename));
static int get_owner __ARGS((char *directory, char *cf_name, char **owner));
static void lpd __ARGS((int s, void *unused, void *p));
static int receive_control_file __ARGS((struct LPDtrans *LPD,
unsigned long filesize, int s));
static int receive_data_file __ARGS((char *filename,
unsigned long filesize, int s));
static int receive_job __ARGS((struct LPDtrans *LPD));
static int remove_files __ARGS((char *directory, char *cf_name));
static int remove_job __ARGS((struct LPDtrans *LPD, char *local_parms));
static int send_queue __ARGS((struct LPDtrans *LPD, int type, char *local_parms));
static int validate_control_file __ARGS((struct LPDtrans *LPD, char *priority));
static int Slpd = -1; /* Prototype socket for service */
int secure = 0; /* default to non-secure */
/* Start up LPD service */
int
lpdstart(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct sockaddr_in lsocket;
struct sockaddr_in from_addr;
int c, s, from_len;
if( Slpd != -1 ) {
/* Already running! */
return 0;
}
secure = 0;
optind = 1; /* reinit getopt() */
loop: while((c = getopt(argc,argv,"s")) != EOF){
switch( c ) {
case 's': /* secure */
secure = 1;
break;
}
}
psignal( Curproc, 0 ); /* Don't keep the parser waiting */
chname( Curproc, "LPD listener" );
init_queue_status();
/*
* Print any entries remaining
*/
newproc( "LPDstartup", 2048, start_all_unspoolers, 0, NULL, NULL, 0 );
/*
* Wait for incoming jobs
*/
lsocket.sin_family = AF_INET;
lsocket.sin_addr.s_addr = INADDR_ANY;
if( optind < argc )
lsocket.sin_port = atoi( argv[optind]);
else
lsocket.sin_port = IPPORT_LPD;
Slpd = socket( AF_INET, SOCK_STREAM, 0 );
bind( Slpd, (char *)&lsocket, sizeof(lsocket) );
listen( Slpd, 1 );
for( ;; ) {
if( (s = accept( Slpd, (char *)&from_addr, &from_len )) == -1 )
break; /* Service is shutting down */
if( availmem() < Memthresh ) {
RESPOND_ERR( s );
usprintf( s, "server low on memory\n" );
shutdown( s, 1 );
} else {
#ifdef notdef
if( from_addr.sin_port > 1023 ) {
/* not allowed */
close_s( s );
continue;
}
#endif
/* Spawn a server */
newproc( "LPDserv", 4096, lpd, s, NULL, NULL, 0 );
}
}
return 0;
}
static void
lpd(s,unused,p)
int s; /* Socket with user connection */
void *unused;
void *p;
{
struct LPDtrans LPD;
char buf[512], printer[64], *remote_host, *sp, *dp;
int cnt = MAXSOCKSIZE;
union sp sockp;
char sc[MAXSOCKSIZE];
struct sockaddr_in from_addr;
memset( (char *)&LPD, 0, sizeof(LPD) ); /* Start with clear slate */
sockowner( s, Curproc ); /* We own it now */
sockmode( s, SOCK_BINARY );
LPD.remote = s;
log( s,"open LPD" );
remote_host = NULL;
/*
* Obtain the "domain name" of the remote host to check permissions
*/
getpeername( s, sc, &cnt );
sockp.p = sc;
#ifdef LPD_DEBUG
tprintf( "secure %d from %s\n", secure, psocket(sc) );
#endif
remote_host = resolve_a( sockp.in->sin_addr.s_addr, 0 );
if( *(remote_host + strlen(remote_host) - 1) == '.' )
*(remote_host + strlen(remote_host) - 1) = NULL;
#ifdef LPD_DEBUG
tprintf( "remote host = %s\n", remote_host );
tflush();
#endif
loop: if( (cnt = recvline( s, buf, sizeof(buf) )) == -1){
/* He closed on us */
goto finish;
}
if( cnt == 0 ){
/* Can't be a legal LPD command */
RESPOND_ERR( LPD.remote );
goto loop;
}
rip( buf );
for( sp = buf+1, dp = printer; *sp && *sp != ' '; *dp++ = *sp++ )
;
*dp = NULL;
#ifdef LPD_DEBUG
tprintf( "LPD: request %d - %s\n", *buf, buf+1 );
#endif
if( START_CMD <= *buf && *buf <= REMOVE_CMD ) {
LPD.pc = NULL;
if( (LPD.name = read_printcap( &LPD, printer )) == NULL ) {
RESPOND_ERR( LPD.remote );
usprintf( LPD.remote, "Printer %s (%s) not found.\n", printer, Hostname );
goto finish;
}
}
if( secure && !check_permission( remote_host, NULL, LPD.name, NULL ) ) {
RESPOND_ERR( LPD.remote );
usprintf( LPD.remote, "Your host is not authorized to use %s.\n", buf+1 );
/*
* Setup log file
*/
LPD.logfp = fopen( LPD.pc->LF, "a" );
lpd_log( &LPD, "lpd: permission rejected for %s, %s, %s, %c ", remote_host, NULL, LPD.name, NULL );
if( LPD.logfp )
fclose( LPD.logfp );
goto finish;
}
switch( *buf ) {
case START_CMD: /* Check queue and print */
/*
* Line format: \1printer\n
*/
RESPOND_OK( LPD.remote );
close_s( s ); /* close connection */
start_unspooler( LPD.name );
break;
case RECEIVE_CMD: /* Submit a print job */
/*
* Line format: \2printer\n
*/
receive_job( &LPD );
break;
case SQUEUE_CMD: /* Display Queue (short form) */
/*
* Line format: \3printer [users ...] [jobs ...]\n
*/
send_queue( &LPD, SQUEUE_CMD, buf+1 );
break;
case QUEUE_CMD: /* Display Queue (long form) */
/*
* Line format: \4printer [users ...] [jobs ...]\n
*/
send_queue( &LPD, QUEUE_CMD, buf+1 );
break;
case REMOVE_CMD: /* Remove a job from Queue */
/*
* Line format: \5printer person [users ...] [job ...]\n
*/
remove_job( &LPD, buf+1 );
break;
default: /* Invalid command */
RESPOND_ERR( LPD.remote );
usprintf( LPD.remote, "Invalid command\n" );
}
finish:
log( LPD.remote,"close LPD" );
/* Clean up */
close_s( LPD.remote );
if( LPD.pc )
free( LPD.pc );
if( LPD.name )
free( LPD.name );
if( remote_host )
free( remote_host );
}
/* Shut down LPD server */
int
lpd0(argc,argv,p)
int argc;
char *argv[];
void *p;
{
close_s(Slpd);
Slpd = -1;
free_queue_status();
return 0;
}
static int
receive_job( LPD )
struct LPDtrans *LPD;
{
char *strdup(), priority;
int cnt, sequence;
unsigned long filesize;
char buffer[512], newfilename[13], *path, *remotefile, *strchr();
FILE *fp;
sequence = get_new_sequence_no( LPD );
sprintf( newfilename, "xfAA%03d", sequence );
LPD->xlat_table = (struct LPDxlat *)callocw( 1, sizeof( struct LPDxlat ) );
#ifdef LPD_DEBUG
tprintf( "receive_job( %s )\n", newfilename );
tflush();
#endif
RESPOND_OK( LPD->remote );
for( ;; ) {
if( (cnt = recvline( LPD->remote, buffer, sizeof(buffer) )) == -1 ){
/* He closed on us */
break;
}
if( cnt == 0 ){
/* Can't be a legal LPD command */
RESPOND_ERR( LPD->remote );
continue;
}
rip(buffer);
#ifdef LPD_DEBUG
tprintf( "subcommand %d+%s\n", *buffer, buffer+1 );
tflush();
#endif
switch( *buffer ) {
case ABORT_SCMD: /* flush current files */
cleanup( LPD->pc->SD, newfilename );
break;
case RECEIVE_CF_SCMD: /* control file */
filesize = atol( buffer+1 );
if( receive_control_file( LPD, filesize, LPD->remote ) < 0 ) {
tprintf( "could not receive control file\n" );
cleanup( LPD->pc->SD, newfilename );
return -1;
}
if( validate_control_file( LPD, &priority ) < 0 ) {
RESPOND_ERR( LPD->remote );
cleanup( LPD->pc->SD, newfilename );
return -1;
} else {
RESPOND_OK( LPD->remote );
}
/*
* Write out control file
*/
newfilename[0] = 'c'; /* control file */
newfilename[2] = priority;
newfilename[3] = 'A';
path = pathname( LPD->pc->SD, newfilename );
fixup_and_write_control_file( LPD, path );
free( path );
break;
case RECEIVE_DF_SCMD:
filesize = atol( buffer+1 );
newfilename[0] = 'd'; /* data file */
path = pathname( LPD->pc->SD, newfilename );
remotefile = strchr( buffer+1, ' ' ) + 1;
if( receive_data_file( path, filesize, LPD->remote ) < 0 ) {
tprintf( "could not receive %s(%s)\n", remotefile, path );
cleanup( LPD->pc->SD, newfilename );
free( path );
return -1;
}
free( path );
enter_translation( LPD->xlat_table, newfilename, remotefile );
/* increment file letters */
newfilename[3] = newfilename[3] + 1;
if( newfilename[3] > 'Z' ) {
newfilename[3] = 'A';
newfilename[2] = newfilename[2] + 1;
}
RESPOND_OK( LPD->remote );
break;
}
}
free( LPD->xlat_table );
chname( Curproc, "LPDprint" );
start_unspooler( strdup( LPD->name ) );
}
static int
check_printer( LPD, printer_name )
struct LPDtrans *LPD;
char *printer_name;
{
char *p1, *p2;
p1 = printer_name;
p2 = LPD->name;
while( *p1 && *p1 != ' ' )
*p2++ = *p1++;
p2 = NULL;
}
/*
* cleanup - remove current control and data files
*/
static void
cleanup( spool_dir, filespec )
char *spool_dir, *filespec;
{
char *path;
/* remove all data files */
filespec[0] = 'd';
do {
do {
path = pathname( spool_dir, filespec );
remove( path );
free( path );
} while( filespec[3]-- != 'A' );
filespec[3] = 'Z';
} while( filespec[2]-- != 'A' );
/* remove control file */
filespec[0] = 'c';
filespec[2] = 'A';
filespec[3] = 'A';
path = pathname( spool_dir, filespec );
remove( path );
free( path );
}
static int
receive_data_file( filename, filesize, s )
char *filename;
unsigned long filesize;
int s;
{
int bytes, blocksize;
unsigned long total = 0;
char *buffer, status;
FILE *fp;
#ifdef LPD_DEBUG
tprintf( "receive_data_file( %ld )\n", filesize );
tflush();
#endif
fp = fopen( filename, WRITE_BINARY );
filesize++; /* add in status byte */
blocksize = filesize > BLOCKSIZE ? BLOCKSIZE : filesize;
buffer = (char *)malloc( blocksize );
RESPOND_OK( s );
do {
if( (bytes = recv( s, buffer, blocksize, 0 )) < 1 ) {
free( buffer );
fclose( fp );
return -1;
}
if( total + bytes == filesize ) {
bytes--; /* don't save status byte */
status = *(buffer + bytes);
total++;
}
if( fwrite( buffer, bytes, 1, fp ) == 0 ) {
free( buffer );
fclose( fp );
return -1;
}
total += bytes;
if( filesize - total < BLOCKSIZE )/* handle last portion */
blocksize = filesize - total;
} while( total < filesize );
free( buffer );
fclose( fp );
if( status != STATUS_OK ) {
tprintf( "bad status\n" );
tflush();
return -1;
}
return 0;
}
static int
receive_control_file( LPD, filesize, s )
struct LPDtrans *LPD;
unsigned long filesize;
int s;
{
int c, bytes, blocksize;
unsigned long total = 0;
char *buffer, status;
#ifdef LPD_DEBUG
tprintf( "receive_control_file( %ld )\n", filesize );
tflush();
#endif
LPD->cf_data = (char *)mallocw( filesize+1 ); /* + NULL byte */
buffer = LPD->cf_data;
filesize++; /* add in status byte */
blocksize = filesize > BLOCKSIZE ? BLOCKSIZE : filesize;
RESPOND_OK( s );
do {
if( (bytes = recv( s, buffer, blocksize, 0 )) < 1 ) {
free( LPD->cf_data );
return -1;
}
if( total + bytes == filesize ) {
bytes--; /* don't save status byte */
status = *(buffer + bytes);
total++;
}
buffer += bytes;
total += bytes;
if( filesize - total < BLOCKSIZE )/* handle last portion */
blocksize = filesize - total;
} while( total < filesize );
LPD->cf_data[ filesize-1 ] = NULL; /* add NULL byte */
if( status != STATUS_OK ) {
tprintf( "bad status\n" );
tflush();
return -1;
}
return 0;
}
static int
enter_translation( xlat_table, filename, remotefile )
struct LPDxlat *xlat_table;
char *filename, *remotefile;
{
char *strdup();
int index;
#ifdef LPD_DEBUG
tprintf( "enter_translation( %s, %s )\n", filename, remotefile );
tflush();
#endif
for( index = 0; index < 32; index++ ) {
if( xlat_table->xlat[ index ].dfname == NULL ) {
/* found an empty slot */
xlat_table->xlat[ index ].dfname = strdup( remotefile );
xlat_table->xlat[ index ].dos_dfname = strdup( filename );
return;
}
}
YIELD;
}
static int
fixup_and_write_control_file( LPD, filename )
struct LPDtrans *LPD;
char *filename;
{
char *ptr, *strchr(), old_filename[128], *optr;
int index;
FILE *fp;
#ifdef LPD_DEBUG
tprintf( "fixup_and_write_control_file( %s )\n", filename );
tflush();
#endif
fp = fopen( filename, WRITE_TEXT );
ptr = LPD->cf_data;
while( *ptr ) {
if( *ptr > 'a' && *ptr <'z' || *ptr == 'U' ) {
/* translation needed */
putc( *ptr++, fp );
optr = old_filename;
while( *ptr && *ptr != '\n' )
*optr++ = *ptr++;
*optr = NULL;
for( index = 0; index < 32; index++ ) {
if( strcmp( LPD->xlat_table->xlat[ index ].dfname, old_filename ) == 0 ) {
/* found the translation */
fputs( LPD->xlat_table->xlat[ index ].dos_dfname, fp );
break;
}
}
}
while( *ptr && *ptr != '\n' )
putc( *ptr++, fp );
if( *ptr == NULL )
break;
putc( *ptr++, fp ); /* output linefeed */
YIELD;
}
fclose( fp );
free( LPD->cf_data );
/*
* Clean up translations
*/
for( index = 0; index < 32; index++ ) {
if( LPD->xlat_table->xlat[ index ].dfname != NULL ) {
/* clean slot */
free( LPD->xlat_table->xlat[ index ].dfname );
free( LPD->xlat_table->xlat[ index ].dos_dfname );
LPD->xlat_table->xlat[ index ].dfname = NULL;
}
}
YIELD;
return 0;
}
static int
validate_control_file( LPD, priority )
struct LPDtrans *LPD;
char *priority;
{
char *ptr, host[64], user[32], class[32];
int index;
#ifdef LPD_DEBUG
tprintf( "validating control file\n" );
tflush();
#endif
memset( host, 0, sizeof( host ) );
memset( user, 0, sizeof( user ) );
memset( class, 0, sizeof( class ) );
/*
* Extract info to test permissions
*/
ptr = LPD->cf_data;
while( *ptr ) {
if( *ptr == 'H' ) { /* host name */
index = 0;
while( *++ptr && *ptr != '\n' )
host[index++] = *ptr;
host[index] = NULL;
} else if( *ptr == 'P' ) { /* login name */
index = 0;
while( *++ptr && *ptr != '\n' )
user[index++] = *ptr;
user[index] = NULL;
} else if( *ptr == 'C' ) { /* class or priority */
index = 0;
while( *++ptr && *ptr != '\n' )
class[index++] = *ptr;
class[index] = NULL;
}
while( *ptr && *ptr != '\n' )
ptr++;
if( *ptr++ == NULL )
break;
YIELD;
}
*priority = *class;
if( priority == 0 )
*priority = 'Z';
if( !isascii( *priority ) || !isupper( *priority ) )
*priority = 'Z';
YIELD;
if( secure && !check_permission( host, user, LPD->name, priority ) ) {
/*
* Setup log file
*/
LPD->logfp = fopen( LPD->pc->LF, "a" );
lpd_log( LPD, "lpd: permission rejected for %s, %s, %s, %c ", host, user, LPD->name, *priority );
if( LPD->logfp )
fclose( LPD->logfp );
return -1;
}
YIELD;
return 0;
}
int
is_lpd_active(void)
{
return( (Slpd == -1) ? 0 : 1 );
}
static char *parms[ MAX_PARMS ];
static int parms_count;
char *
extract_parms( local_parms, extra )
char *local_parms;
int extra;
{
char *cp, *skipp;
cp = strtok( local_parms, " " ); /* skip <printer> */
while( --extra > 0 )
skipp = strtok( NULL, " " ); /* skip other unused parms */
/*
* Build parameter list
*/
parms_count = 0;
while( parms_count < MAX_PARMS && (cp = strtok( NULL, " " )) != NULL )
parms[ parms_count++ ] = cp;
return( skipp ); /* last skipped parameter */
}
int
send_queue( LPD, type, local_parms )
struct LPDtrans *LPD;
int type;
char *local_parms;
{
int active;
unsigned int flags, next_seq, job_count, job;
char *message, status[32], line[81];
char *path, *active_job, *strdup();
struct job_entry *job_list;
struct stat fstatus;
FILE *cfp;
/* job specific info */
char *owner, host[12], files[21], date[12], *suffix;
long size;
#ifdef LPD_DEBUG
tprintf( "send_queue( %s, %d )\n", LPD->name, type );
tflush();
#endif
(void)extract_parms( local_parms, 1 );
active = is_unspooler_active( LPD->name, &active_job );
job_count = get_job_list( LPD->pc->SD, &job_list );
read_status( LPD->name, &flags, &next_seq, &message );
*status = NULL;
if( (flags & QUEUE_ENABLED) == 0 )
strcat( status, "no spooling" );
if( (flags & PRINT_ENABLED) == 0 ) {
if( *status )
strcat( status, ", " );
strcat( status, "no printing" );
}
if( type == SQUEUE_CMD ) {
usprintf( LPD->remote, "%s: %d jobs", LPD->name, job_count );
if( *status )
usprintf( LPD->remote, " (%s)", status );
usputc( LPD->remote, '\n' );
} else {
usprintf( LPD->remote, "Printer '%s' (%s)", LPD->name, Hostname );
if( LPD->pc->CM )
usprintf( LPD->remote, " %s", LPD->pc->CM );
usputc( LPD->remote, ':' );
if( *status )
usprintf( LPD->remote, " (%s)", status );
usputc( LPD->remote, '\n' );
if( job_count > 0 && !active )
usputs( LPD->remote, "Warning: no unspooler present\n" );
usprintf( LPD->remote, " %s\n", message );
}
if( job_count > 0 && type == QUEUE_CMD ) {
usputs( LPD->remote, " Rank Owner Pr Job Host Files" );
usputs( LPD->remote, " Size Date\n" );
}
/*
* Read each control file for information and display
*/
for( job = 0; job < job_count; job++ ) {
if( !is_job_specified( job_list[ job ].j_name ) ) {
free( job_list[ job ].j_name );
continue;
}
size = 0;
*host = NULL;
*files = NULL;
path = pathname( LPD->pc->SD, job_list[ job ].j_name );
if( (cfp = fopen( path, "r" )) == NULL ) {
free( path );
continue;
}
stat( path, &fstatus );
free( path );
sprintf( date, "%7.7s%4.4s", ctime( &fstatus.st_mtime ) + 4,
ctime( &fstatus.st_mtime ) + 20 );
while( fgets( line, 80, cfp ) != NULL ) {
rip( line );
if( islower( *line ) ) {
path = pathname( LPD->pc->SD, line+1 );
if( stat( path, &fstatus ) != 0 ) {
free( path );
continue;
}
free( path );
size += fstatus.st_size;
} else if( *line == 'P' ) {
owner = strdup( line+1 );
} else if( *line == 'N' ) {
if( *files )
trunc_strcat( files, ",", 20 );
trunc_strcat( files, line+1, 20 );
} else if( *line == 'H' ) {
trunc_strcat( host, line+1, 11 );
}
}
fclose( cfp );
if( type == SQUEUE_CMD ) { /* short form */
usprintf( LPD->remote, "%d cf%s: %s\n", job+1, job_list[ job ].j_name+2, owner );
} else { /* long form */
if( strcmp( active_job, job_list[ job ].j_name ) == 0 ) {
strcpy( line, "active" );
} else {
switch( job+1 ) {
case 1: suffix = "st"; break;
case 2: suffix = "nd"; break;
case 3: suffix = "rd"; break;
default: suffix = "th"; break;
}
sprintf( line, "%d%s", job+1, suffix );
}
usprintf( LPD->remote, "%6s %-11s %-c %-3s %-11s %-20s %-6ld %s\n",
line, /* rank */
owner, /* owner */
job_list[ job ].j_name[2], /* priority */
job_list[ job ].j_name + 4, /* job */
host, /* host */
files, /* files in job */
size, /* job size */
date /* date submitted */
);
}
free( job_list[ job ].j_name );
free( owner );
}
if( job_count > 0 )
free( job_list );
}
int
trunc_strcat( dest, source, max_length )
char *dest, *source;
int max_length;
{
strncat( dest, source, max_length - strlen( dest ) );
}
int
is_job_specified( cf_name )
char *cf_name;
{
int parm, job_spec, job_no;
if( parms_count == 0 ) /* match all */
return 1;
for( parm = 0; parm < parms_count; parm++ ) {
if( isdigit( *parms[ parm ] ) ) { /* job number specified */
job_spec = atoi( parms[ parm ] );
job_no = atoi( cf_name + 4 );
if( job_spec == job_no )
return 1;
} /* user name - NOT SUPPORTED */
}
return 0;
}
static int
get_owner( directory, cf_name, owner )
char *directory, *cf_name, **owner;
{
char *path, line[81];
FILE *cfp;
*owner = NULL;
path = pathname( directory, cf_name );
if( (cfp = fopen( path, "r" )) == NULL ) {
free( path );
return -1;
}
free( path );
while( fgets( line, 80, cfp ) != NULL ) {
rip( line );
if( *line == 'P' )
*owner = strdup( line+1 );
}
fclose( cfp );
return 0;
}
static int
remove_files( directory, cf_name )
char *directory, *cf_name;
{
char *path, line[81];
FILE *cfp;
path = pathname( directory, cf_name );
if( (cfp = fopen( path, "r" )) == NULL ) {
free( path );
return -1;
}
free( path );
while( fgets( line, 80, cfp ) != NULL ) {
rip( line );
if( *line == 'U' ) {
path = pathname( directory, line+1 );
remove( path );
free( path );
}
}
fclose( cfp );
path = pathname( directory, cf_name );
remove( path );
free( path );
return 0;
}
static int
remove_job( LPD, local_parms )
struct LPDtrans *LPD;
char *local_parms; /* <printer> <user> <jobs> */
{
int all, active, job, job_count;
char *user, *owner, *cp;
char *active_job;
struct job_entry *job_list;
usprintf( LPD->remote, "Printer '%s' (%s):\n", LPD->name, Hostname );
user = extract_parms( local_parms, 2 );
active = is_unspooler_active( LPD->name, &active_job );
job_count = get_job_list( LPD->pc->SD, &job_list );
/*
* Check each job against request
*/
for( job = 0; job < job_count; job++ ) {
if( get_owner( LPD->pc->SD, job_list[ job ].j_name, &owner ) < 0 )
continue;
if( strcmp( user, owner ) != 0 ) { /* not owner of job */
free( owner );
continue;
}
if( is_job_specified( job_list[ job ].j_name ) ) {
usprintf( LPD->remote, "removing cf%s, job %-3s owner %s\n",
job_list[ job ].j_name + 2,
job_list[ job ].j_name + 3,
owner );
if( active && strcmp( job_list[ job ].j_name, active_job ) == 0 ) {
/* unspooler is processing our job, kill it */
usprintf( LPD->remote, "killing off %s unspooler\n", LPD->name );
kill_unspooler( LPD->name );
}
remove_files( LPD->pc->SD, job_list[ job ].j_name );
YIELD;
}
free( job_list[ job ].j_name );
free( owner );
}
free( job_list );
YIELD;
return 0;
}